home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sprite 1984 - 1993
/
Sprite 1984 - 1993.iso
/
src
/
machserver
/
1.098
/
vm
/
vmServer.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-07-26
|
12KB
|
459 lines
/* vmServer.c -
*
* This file contains routines that read and write pages to/from the page
* server and file server.
*
* Copyright (C) 1985 Regents of the University of California
* All rights reserved.
*/
#ifndef lint
static char rcsid[] = "$Header: /sprite/src/kernel/vm/RCS/vmServer.c,v 9.7 91/07/26 17:05:16 shirriff Exp $ SPRITE (Berkeley)";
#endif not lint
#include <sprite.h>
#include <vm.h>
#include <vmInt.h>
#include <vmSwapDir.h>
#include <lock.h>
#include <status.h>
#include <sched.h>
#include <sync.h>
#include <dbg.h>
#include <list.h>
#include <string.h>
#include <stdlib.h>
#include <proc.h>
#include <stdio.h>
Boolean vmUseFSReadAhead = TRUE;
extern Boolean vm_NoStickySegments;
char *sprintf();
/*
* Condition to wait on when want to do a swap file operation but someone
* is already doing one. This is used for synchronization of opening
* of swap files. It is possible that the open of the swap file could
* happen more than once if the open is not synchronized.
*/
Sync_Condition swapFileCondition;
void Fscache_BlocksUnneeded();
/*
*----------------------------------------------------------------------
*
* VmSwapFileLock --
*
* Set a lock on the swap file for the given segment. If the lock
* is already set then wait.
*
* Results:
* None.
*
* Side effects:
* Flags field in segment table entry is modified to make the segment
* locked.
*----------------------------------------------------------------------
*/
ENTRY void
VmSwapFileLock(segPtr)
register Vm_Segment *segPtr;
{
LOCK_MONITOR;
while (segPtr->flags & VM_SWAP_FILE_LOCKED) {
(void) Sync_Wait(&swapFileCondition, FALSE);
}
segPtr->flags |= VM_SWAP_FILE_LOCKED;
UNLOCK_MONITOR;
}
/*
*----------------------------------------------------------------------
*
* VmSwapFileUnlock --
*
* Clear the lock on the swap file for the given segment.
*
* Results:
* None.
*
* Side effects:
* Flags field in segment table entry is modified to make the segment
* unlocked and anyone waiting for the segment is awakened.
*----------------------------------------------------------------------
*/
ENTRY void
VmSwapFileUnlock(segPtr)
register Vm_Segment *segPtr;
{
LOCK_MONITOR;
segPtr->flags &= ~VM_SWAP_FILE_LOCKED;
Sync_Broadcast(&swapFileCondition);
UNLOCK_MONITOR;
}
/*
*----------------------------------------------------------------------
*
* VmPageServerRead --
*
* Read the given page from the swap file into the given page frame.
* This routine will panic if the swap file does not exist.
*
* NOTE: It is assumed that the page frame that is to be written into
* cannot be given to another segment.
*
* Results:
* SUCCESS if the page server could be read from or an error if either
* a swap file could not be opened or the page server could not be
* read from the swap file.
*
* Side effects:
* The hardware page is written into.
*
*----------------------------------------------------------------------
*/
ReturnStatus
VmPageServerRead(virtAddrPtr, pageFrame)
Vm_VirtAddr *virtAddrPtr;
unsigned int pageFrame;
{
register int mappedAddr;
register Vm_Segment *segPtr;
int status;
int pageToRead;
segPtr = virtAddrPtr->segPtr;
if (!(segPtr->flags & VM_SWAP_FILE_OPENED)) {
panic("VmPageServerRead: Trying to read from non-existent swap file.\n");
}
if (segPtr->type == VM_STACK) {
pageToRead = mach_LastUserStackPage - virtAddrPtr->page;
} else if (segPtr->type == VM_SHARED) {
pageToRead= virtAddrPtr->page - segOffset(virtAddrPtr) +
(virtAddrPtr->sharedPtr->fileAddr>>vmPageShift);
} else {
pageToRead = virtAddrPtr->page - segPtr->offset;
}
/*
* Map the page into the kernel's address space and fill it from the
* file server.
*/
mappedAddr = (int) VmMapPage(pageFrame);
status = Fs_PageRead(segPtr->swapFilePtr, (Address) mappedAddr,
pageToRead << vmPageShift, vm_PageSize, FS_SWAP_PAGE);
VmUnmapPage((Address) mappedAddr);
return(status);
}
/*
*----------------------------------------------------------------------
*
* VmPageServerWrite --
*
* Write the given page frame to the swap file. If the swap file is
* not open yet then it will be open.
*
* NOTE: It is assumed that the page frame that is to be read from
* cannot be given to another segment.
*
* Results:
* SUCCESS if the page server could be written to or an error if either
* a swap file could not be opened or the page server could not be
* written to.
*
* Side effects:
* If no swap file exists, then one is created.
*
*----------------------------------------------------------------------
*/
ReturnStatus
VmPageServerWrite(virtAddrPtr, pageFrame, toDisk)
Vm_VirtAddr *virtAddrPtr;
unsigned int pageFrame;
Boolean toDisk;
{
register int mappedAddr;
register Vm_Segment *segPtr;
ReturnStatus status;
int pageToWrite;
vmStat.pagesWritten++;
segPtr = virtAddrPtr->segPtr;
/*
* Lock the swap file while opening it so that we don't have more than
* one swap file open at a time.
*/
VmSwapFileLock(segPtr);
if (!(segPtr->flags & VM_SWAP_FILE_OPENED)) {
status = VmOpenSwapFile(segPtr);
if (status != SUCCESS) {
VmSwapFileUnlock(segPtr);
return(status);
}
}
VmSwapFileUnlock(segPtr);
if (segPtr->type == VM_STACK) {
pageToWrite = mach_LastUserStackPage - virtAddrPtr->page;
} else {
pageToWrite = virtAddrPtr->page - segOffset(virtAddrPtr);
}
/*
* Map the page into the kernel's address space and write it out.
*/
VmMach_FlushPage(virtAddrPtr, FALSE);
mappedAddr = (int) VmMapPage(pageFrame);
status = Fs_PageWrite(segPtr->swapFilePtr, (Address) mappedAddr,
pageToWrite << vmPageShift, vm_PageSize, toDisk);
VmUnmapPage((Address) mappedAddr);
return(status);
}
/*
*----------------------------------------------------------------------
*
* VmCopySwapSpace --
*
* Copy the swap space for all pages that have been written out to swap
* space for the source segment into the destination segments swap space.
*
* Results:
* Error if swap file could not be opened, read or written. Otherwise
* SUCCESS is returned.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
ReturnStatus
VmCopySwapSpace(srcSegPtr, destSegPtr)
register Vm_Segment *srcSegPtr;
register Vm_Segment *destSegPtr;
{
register int page;
register Vm_PTE *ptePtr;
ReturnStatus status = SUCCESS;
register int i;
VmSwapFileLock(srcSegPtr);
if (!(srcSegPtr->flags & VM_SWAP_FILE_OPENED)) {
VmSwapFileUnlock(srcSegPtr);
return(SUCCESS);
}
VmSwapFileUnlock(srcSegPtr);
VmSwapFileLock(destSegPtr);
if (!(destSegPtr->flags & VM_SWAP_FILE_OPENED)) {
status = VmOpenSwapFile(destSegPtr);
if (status != SUCCESS) {
VmSwapFileUnlock(destSegPtr);
return(status);
}
}
VmSwapFileUnlock(destSegPtr);
if (destSegPtr->type == VM_STACK) {
page = destSegPtr->numPages - 1;
ptePtr = VmGetPTEPtr(destSegPtr, mach_LastUserStackPage -
destSegPtr->numPages + 1);
} else {
page = 0;
ptePtr = destSegPtr->ptPtr;
}
for (i = 0; i < destSegPtr->numPages; i++, VmIncPTEPtr(ptePtr, 1)) {
if (*ptePtr & VM_IN_PROGRESS_BIT) {
*ptePtr &= ~VM_IN_PROGRESS_BIT;
/*
* The page is on the swap file and not in memory. Need to copy
* the page in the file.
*/
vmStat.swapPagesCopied++;
status = Fs_PageCopy(srcSegPtr->swapFilePtr,
destSegPtr->swapFilePtr,
page << vmPageShift, vm_PageSize);
if (status != SUCCESS) {
break;
}
}
if (destSegPtr->type == VM_STACK) {
page--;
} else {
page++;
}
}
return(status);
}
/*
*----------------------------------------------------------------------
*
* VmFileServerRead --
*
* Read the given page from the file server into the given page frame.
*
* NOTE: It is assumed that the page frame that is to be written into
* cannot be given to another segment.
*
* Results:
* Error if file server could not be read from, SUCCESS otherwise.
*
* Side effects:
* The hardware page is written into.
*
*----------------------------------------------------------------------
*/
ReturnStatus
VmFileServerRead(virtAddrPtr, pageFrame)
Vm_VirtAddr *virtAddrPtr;
unsigned int pageFrame;
{
register int mappedAddr;
register Vm_Segment *segPtr;
int length;
int status;
int offset;
segPtr = virtAddrPtr->segPtr;
/*
* Map the page frame into the kernel's address space.
*/
mappedAddr = (int) VmMapPage(pageFrame);
/*
* The address to read is just the page offset into the segment
* ((page - offset) << vmPageShift) plus the offset of this segment into
* the file (fileAddr).
* (We have to use the right offset for shared memory.
*/
length = vm_PageSize;
if (segPtr->type == VM_SHARED) {
if (virtAddrPtr->sharedPtr == (Vm_SegProcList *)NIL) {
printf("*** NIL sharedPtr in VmFileServerRead\n");
return FAILURE;
}
offset = ((virtAddrPtr->page - segOffset(virtAddrPtr)) << vmPageShift)
+ virtAddrPtr->sharedPtr->fileAddr;
} else {
offset = ((virtAddrPtr->page - segOffset(virtAddrPtr)) << vmPageShift)
+ segPtr->fileAddr;
}
if (vmPrefetch || !vmUseFSReadAhead) {
/*
* If we are using prefetch then do the reads ourselves.
*/
if (segPtr->type == VM_CODE && !vm_NoStickySegments) {
status = Fs_PageRead(segPtr->filePtr, (Address)mappedAddr, offset,
length, FS_CODE_PAGE);
} else {
status = Fs_PageRead(segPtr->filePtr, (Address)mappedAddr, offset,
length, FS_HEAP_PAGE);
}
} else {
/*
* No prefetch so use the file system full blown mechanism so
* that we can take advantage of its read ahead.
*/
status = Fs_Read(segPtr->filePtr, (Address) mappedAddr, offset,
&length);
if (status == SUCCESS && !vm_NoStickySegments &&
segPtr->type == VM_CODE) {
/*
* Tell the file system that we just read some file system blocks
* into virtual memory.
*/
Fscache_BlocksUnneeded(segPtr->filePtr, offset, vm_PageSize, TRUE);
}
}
VmUnmapPage((Address) mappedAddr);
if (status != SUCCESS) {
printf("%s VmFileServerRead: Error %x from Fs_Read or Fs_PageRead\n",
"Warning:", status);
return(status);
}
return(SUCCESS);
}
/*
*----------------------------------------------------------------------
*
* VmCopySwapPage --
*
* Copy the swap page from the source segment's swap file to the
* destination.
*
* Results:
* Error if swap file could not be opened, read or written. Otherwise
* SUCCESS is returned.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
ReturnStatus
VmCopySwapPage(srcSegPtr, virtPage, destSegPtr)
register Vm_Segment *srcSegPtr; /* Source for swap file. */
int virtPage; /* Virtual page to copy. */
register Vm_Segment *destSegPtr; /* Destination swap file. */
{
int pageToCopy;
ReturnStatus status;
/*
* Lock the swap file while opening it so that we don't have more than
* one swap file open at a time.
*/
VmSwapFileLock(destSegPtr);
if (!(destSegPtr->flags & VM_SWAP_FILE_OPENED)) {
status = VmOpenSwapFile(destSegPtr);
if (status != SUCCESS) {
VmSwapFileUnlock(destSegPtr);
return(status);
}
}
VmSwapFileUnlock(destSegPtr);
vmStat.swapPagesCopied++;
if (destSegPtr->type == VM_STACK) {
pageToCopy = mach_LastUserStackPage - virtPage;
} else {
pageToCopy = virtPage - destSegPtr->offset;
}
status = Fs_PageCopy(srcSegPtr->swapFilePtr,
destSegPtr->swapFilePtr,
pageToCopy << vmPageShift, vm_PageSize);
return(status);
}